package test;

import java.util.concurrent.*;

class ProcessExclusion extends Thread {
	private int threadId;
	private Semaphore semaphore;

	public ProcessExclusion(Semaphore semaphore) {
		this.semaphore = semaphore;
	}

	public void setThreadId(int threadId) {
		this.threadId = threadId;
	}

	private int random(int n) {
		return (int) Math.round(n * Math.random());
	}

	private void busyCode() {
		int sleepPeriod = random(500);
		
		try {
			sleep(sleepPeriod);
		} catch (InterruptedException e) {
		}
	}

	private void noncriticalCode() {
		System.out.println("noncritical Code "+Thread.currentThread().getId());
		busyCode();
	}

	private void criticalCode() {
		System.out.println("critical Code "+Thread.currentThread().getId());
		busyCode();
	}

	public void run() {
		for (int i = 0; i < 3; i++) {
			try {
				semaphore.acquire();
				criticalCode();
				semaphore.release();
			} catch (InterruptedException e) {
				System.out.println("Exception " + e.toString());
			}
		}
		for (int i = 0; i < 3; i++) {
			noncriticalCode();
		}
	}

	public static void main(String[] args) {
		final int numberOfProcesses = 3;
		final int numberOfPermits = 2;

		Semaphore semaphore = new Semaphore(numberOfPermits, true);
		ProcessExclusion p[] = new ProcessExclusion[numberOfProcesses];

		for (int i = 0; i < numberOfProcesses; i++) {
			p[i] = new ProcessExclusion(semaphore);
			p[i].setThreadId(p[i].hashCode());
			p[i].start();
		}
	}
}